package com.yuneec.fly.models;

import java.net.DatagramPacket;

public class UdpMessage {
    private final static double FLOAT_CHANGE = 100000;

    public int exposureValue;
    public int focalInstance; //unit: millimeter

    public String maxFocusValue;
    public String currentFocusValue;
    public String minFocusValue;

    public String maxShutterSpeed;
    public String currentShutterSpeed;
    public String minShutterSpeed;

    public static UdpMessage parseUdpMessage(DatagramPacket receiverPacket) {
        int receiveLength = receiverPacket.getLength();
        byte[] receiveData = receiverPacket.getData();

        if (receiveLength <= 48) {
            return null;
        }
        int focusFrameNumber = receiveData[47] & 0xff;
        int focusOffset = 48 + (focusFrameNumber * 16);
//        Log.i(TAG, "focusFrameNumber: " + focusFrameNumber + ", focusOffset: " + focusOffset);

        if (receiveLength <= (focusOffset + 39)) {
            return null;
        }
        int offset = focusOffset;
//        Log.i(TAG, "data: " + byteToString(receiveData, 0, 39 + offset));
        short avMaxNumerator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));
        short avMaxDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));

        short avMinNumerator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));
        short avMinDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));

        short avCurrentNumerator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));
        short avCurrentDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));

        short tvMaxNumerator = (short) ((receiveData[offset++] << 8) | (short) (receiveData[offset++] & 0xff));
        short tvMaxDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));


        short tvMinNumerator = (short) ((receiveData[offset++] << 8) | (short) (receiveData[offset++] & 0xff));
        short tvMinDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));

        short tvCurrentNumerator = (short) ((receiveData[offset++] << 8) | (short) (receiveData[offset++] & 0xff));
        short tvCurrentDenominator = (short) ((receiveData[offset++] << 8) | (receiveData[offset++] & 0xff));

        offset += 12;
        int currentExposure = receiveData[offset++];
        int focalInstance = (receiveData[offset++] << 8) | (receiveData[offset++]);

        float avMaxValue = (float) avMaxNumerator / (float) avMaxDenominator;
        float avMinValue = (float) avMinNumerator / (float) avMinDenominator;
        float avCurrentValue = (float) avCurrentNumerator / (float) avCurrentDenominator;


        float tvMaxValue = (float) tvMaxNumerator / (float) tvMaxDenominator;
        float tvMinValue = (float) tvMinNumerator / (float) tvMinDenominator;
        float tvCurrentValue = (float) tvCurrentNumerator / (float) tvCurrentDenominator;

        UdpMessage udpMessage = new UdpMessage();
        udpMessage.exposureValue = currentExposure;
        udpMessage.focalInstance = focalInstance;

        udpMessage.maxFocusValue = String.format("F%.1f", Math.pow(2, avMaxValue / 2));
        udpMessage.currentFocusValue = String.format("F%.1f", Math.pow(2, avCurrentValue / 2));
        udpMessage.minFocusValue = String.format("F%.1f", Math.pow(2, avMinValue / 2));

        double tvMaxConvertValue = Math.pow(2, -tvMaxValue);
        double tvMinConvertValue = Math.pow(2, -tvMinValue);
        double tvCurrentConvertValue = Math.pow(2, -tvCurrentValue);

        String lastSecondString = "s";
        if (tvMaxConvertValue >= 1) {
            udpMessage.maxShutterSpeed = String.format("%.1f%s", tvMaxConvertValue, lastSecondString);
        } else {
            udpMessage.maxShutterSpeed = toFraction(tvMaxConvertValue) + lastSecondString;
        }

        if (tvMinConvertValue > 1) {
            udpMessage.minShutterSpeed = String.format("%.1f%s", tvMinConvertValue, lastSecondString);
        } else {
            udpMessage.minShutterSpeed = toFraction(tvMinConvertValue) + lastSecondString;
        }

        if (tvCurrentConvertValue > 1) {
            udpMessage.currentShutterSpeed = String.format("%.1f%s", tvCurrentConvertValue, lastSecondString);
        } else {
            udpMessage.currentShutterSpeed = toFraction(tvCurrentConvertValue) + lastSecondString;
        }

        return udpMessage;
    }

    public static String toFraction(double d) {
        StringBuilder sb = new StringBuilder();
        if (d < 0) {
            sb.append('-');
            d = -d;
        }
        sb.append(1).append("/");
        if (d >= 0.25) {
            sb.append(Math.round(10 / d) / 10);            //精确到小数点后一位
        } else {
            d = d * FLOAT_CHANGE;
            sb.append(Math.round(FLOAT_CHANGE / d));    //解决1/16000小数点后不能显示数值的问题
        }
        return sb.toString();
    }
}
